package org.jpropelleralt.ledger;

import java.util.List;

import javax.swing.table.TableModel;

import org.jpropelleralt.box.Box;
import org.jpropelleralt.change.Change;
import org.jpropelleralt.node.Node;
import org.jpropelleralt.ref.Ref;

/**
 * A {@link Ledger} contains records, each consisting of the same
 * set of fields. Each field has a fixed class and overall name. In this way,
 * a {@link Ledger} is much like a {@link List} of {@link Node}s, and can
 * be built from that. However {@link Ledger}s do not need to provide for
 * an independent existence of individual records - the {@link Ledger} itself
 * is the only authoritative data source, and the data yielded is not wrapped
 * in {@link Ref}s, etc., making it lighter and more direct as a way of modelling
 * large amounts of homogenous data.
 * 
 * This is essentially a {@link Box} replacement for a {@link TableModel},
 * but is UI independent.
 * 
 * {@link Change}s from this {@link Box} must always be {@link LedgerChange}s, which
 * give more information on the way the {@link Ledger} has changed.
 */
public interface Ledger extends Box {

	/**
	 * Check whether the data in a specific record and field is editable.
	 * @param record	The record index, >=0 and < {@link #recordCount()}
	 * @param field		The field index, >=0 and < {@link #fieldCount()} 
	 * @return	True if data is editable
	 */
	public boolean editable(int record, int field);

	/**
	 * Get the data in a specific record and field.
	 * @param record	The record index, >=0 and < {@link #recordCount()}
	 * @param field		The field index, >=0 and < {@link #fieldCount()} 
	 * @return	Data
	 */
	public Object get(int record, int field);

	/**
	 * Set the data in a specific record and field.
	 * @param record	The record index, >=0 and < {@link #recordCount()}
	 * @param field		The field index, >=0 and < {@link #fieldCount()} 
	 * @param value		The data value to set
	 */
	public void set(int record, int field, Object value);
	
    /**
     * Returns the name of a specific field.
     *
	 * @param field		The field index, >=0 and < {@link #fieldCount()} 
     * @return the name of the field
     */
    public String fieldName(int field);

    /**
     * Returns the {@link Class} of a specific field.
     * 
     * Implementations must ensure that all values returned by
     * {@link #get(int, int)} using the same field index are
     * of this class or a subclass/subinterface.
     *
	 * @param field		The field index, >=0 and < {@link #fieldCount()} 
     * @return the {@link Class} of the field
     */
    public Class<?> fieldClass(int field);
	
	/**
	 * The number of records in the {@link Ledger}.
	 * @return	Current {@link Ledger} size
	 */
	public int recordCount();

	/**
	 * The number of fields in each record of the {@link Ledger}
	 * @return	Current field count.
	 */
	public int fieldCount();
	
}
